#pragma once
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string nullfile = "/dev/null";//系统自带的文件，所有输入都会被丢弃

//进程守护化（即通过守护进程管理目标进程）是保证程序稳定运行、提升系统可靠性的重要手段，
//其核心目的是确保关键进程在异常终止、系统重启或其他意外情况下能够自动恢复，避免服务中断。

//调用Daemon()函数将当前进程守护化，变成孤儿进程，由操作系统领养
//并将标准输入、标准输出、标准错误重定向至/dev/null，
//从而实现将进程与终端分离，使其在后台运行。
void Daemon(const std::string& cwd= "")
{
    // 1. 忽略其他异常信号
    signal(SIGCHLD, SIG_IGN);//忽略子进程退出信号
    signal(SIGPIPE, SIG_IGN);//忽略读端异常关闭信号
    signal(SIGSTOP, SIG_IGN);//忽略停止信号

    // 2. 将自己变成独立的会话
    if (fork() > 0)
        exit(0);
    setsid();//创建一个新的会话，并成为该会话的会话首进程，同时成为新进程组的进程组首进程

    // 3. 更改当前调用进程的工作目录
    if (!cwd.empty()) chdir(cwd.c_str());

    // 4. 标准输入，标准输出，标准错误重定向至/dev/null
    int fd = open(nullfile.c_str(), O_RDWR);
    if(fd > 0)
    {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }
    else
    {
        std::cerr << "open " << nullfile << " failed" << std::endl;
        exit(1);
    }
}